package com.yby6.common.utils;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.util.StopWatch;

/**
 * @ClassName: CodeTimeUtil
 * @create: 2022-05-29 12:42
 * @author: Yang Shuai
 * @since： JDK1.8
 * @OperationTimeUtil: 用于记录代码执行时长$
 **/

public class CodeTimeUtil {

    private static final Logger logger = LogManager.getLogger();

    private final ThreadLocal<Long> start = new ThreadLocal<>();
    private final ThreadLocal<Long> end = new ThreadLocal<>();
    private static CodeTimeUtil OPERATION_TIME_UTIL = null;
    private static StopWatch WATCH = null;
    private static long diff = 0;

    private final String remark;

    /**
     * @param name 对被计算代码块的描述
     */
    public CodeTimeUtil (String remark) {
        this.remark = remark;
    }

    public CodeTimeUtil start () {
        start.set(System.nanoTime());
        return this;
    }

    public CodeTimeUtil end () {
        if (start.get() == null || start.get() == 0) {
            throw new IllegalStateException("计算起始时间点无效");
        }
        end.set(System.nanoTime());
        diff = end.get() - start.get();

        logger.debug(String.format("(%s)->执行耗时:  %s 纳秒 | %s 毫秒 | %s 秒",
                remark, diff + "",
                Math.floorDiv(diff, (long) Math.pow(10, 6)),
                Math.floorDiv(diff, (long) Math.pow(10, 9))));
        start.remove();
        end.remove();
        return this;
    }

    private CodeTimeUtil startWatch () {
        WATCH = new StopWatch();
        WATCH.start(this.remark);
        return this;
    }


    private CodeTimeUtil endWatch () {
        WATCH.stop();
        logger.debug(this.remark + " -> running time ： {}", WATCH.getTotalTimeSeconds() + " s");
        return this;
    }

    public String getName () {
        return remark;
    }

    public static void getStart (String remark) {
        OPERATION_TIME_UTIL = new CodeTimeUtil(remark);
        OPERATION_TIME_UTIL.startWatch();
    }

    public static void getStart () {
        OPERATION_TIME_UTIL = new CodeTimeUtil("获取总消耗");
        OPERATION_TIME_UTIL.startWatch();
    }

    public static void getEnd () {
        OPERATION_TIME_UTIL.endWatch();
    }

}
